package com.yonyou.iuap.ruleengine.relevant.impl;

import com.yonyou.iuap.formula.common.SpringContextHolder;
import com.yonyou.iuap.ruleengine.dto.relevant.CgIdCodesDto;
import com.yonyou.iuap.ruleengine.dto.relevant.RuleItemDto;
import com.yonyou.iuap.ruleengine.dto.relevant.TargetRuleInfoDto;
import com.yonyou.iuap.ruleengine.dto.relevant.TypeCodesDto;
import com.yonyou.iuap.ruleengine.dto.rulemgmt.RelevantRuleGroupInfoDto;
import com.yonyou.iuap.ruleengine.dto.rulemgmt.RuleGroupItemDto;
import com.yonyou.iuap.ruleengine.enums.RelevantDataTypeEnum;
import com.yonyou.iuap.ruleengine.enums.RelevantRuleTypeEnum;
import com.yonyou.iuap.ruleengine.relevant.RelevantRuleLoadService;
import com.yonyou.iuap.ruleengine.service.relevant.RelevantRuleMgmtService;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * TODO
 *
 * @author lihong
 * @date 2022/5/15 19:26
 */
@Service("iUap_YB_RuleEngine_RelevantRuleLoadService")
public class RelevantRuleLoadServiceImpl implements RelevantRuleLoadService {

  private RelevantRuleMgmtService relevantRuleMgmtService;

  @Override
  public TargetRuleInfoDto loadById(Object ruleId) {
    RelevantRuleGroupInfoDto ruleGroupInfo =
            this.getRelevantRuleMgmtService().getByRuleGroupId(ruleId);
    TargetRuleInfoDto targetRuleInfo = getTargetRuleInfo(ruleGroupInfo, null);
    return targetRuleInfo;
  }

  @Override
  public Map<Object, TargetRuleInfoDto> loadByCharacterInfo(
          List<TypeCodesDto> typeCodesList, String bizObjectCode, String tenantId) {
    Map<Object, RelevantRuleGroupInfoDto> ruleGroupInfoMap =
            this.getRelevantRuleMgmtService()
                    .listByCharacterInfo(typeCodesList, bizObjectCode, tenantId);

    Map<Object, TargetRuleInfoDto> targetRuleInfoMap = new HashMap<>();
    for (Object id : ruleGroupInfoMap.keySet()) { // Server端控制好，如果没查到，返回空Map，不能返回null
      TargetRuleInfoDto targetRuleInfo = getTargetRuleInfo(ruleGroupInfoMap.get(id), typeCodesList);
      targetRuleInfoMap.put(id, targetRuleInfo);
    }
    return targetRuleInfoMap;
  }

  @Override
  public Map<Object, TargetRuleInfoDto> loadByBizObjectCode(String bizObjectCode, String tenantId) {
    Map<Object, RelevantRuleGroupInfoDto> ruleGroupInfoMap =
            this.getRelevantRuleMgmtService().listByBizObjectCode(bizObjectCode, tenantId);

    Map<Object, TargetRuleInfoDto> targetRuleInfoMap = new HashMap<>();
    for (Object id : ruleGroupInfoMap.keySet()) {
      TargetRuleInfoDto targetRuleInfo = getTargetRuleInfo(ruleGroupInfoMap.get(id), null);
      targetRuleInfoMap.put(id, targetRuleInfo);
    }
    return targetRuleInfoMap;
  }

/*  @Override
  public Map<Object, TargetRuleInfoDto> loadByCgInfo(
      List<CgIdCodesDto> cgIdCodesList, String bizObjectCode, String tenantId) {
    Map<Object, RelevantRuleGroupInfoDto> ruleGroupInfoMap =
        this.getRelevantRuleMgmtService().listByCgInfo(cgIdCodesList, bizObjectCode, tenantId);

    Map<Object, TargetRuleInfoDto> targetRuleInfoMap = new HashMap<>();
    for (Object id : ruleGroupInfoMap.keySet()) { // Server端控制好，如果没查到，返回空Map，不能返回null
      TargetRuleInfoDto targetRuleInfo =
          getTargetRuleInfo4Cg(ruleGroupInfoMap.get(id), cgIdCodesList);
      targetRuleInfoMap.put(id, targetRuleInfo);
    }
    return targetRuleInfoMap;
  }*/

  @NotNull
  private TargetRuleInfoDto getTargetRuleInfo(
          RelevantRuleGroupInfoDto ruleGroupInfo, List<TypeCodesDto> typeCodesList) {
    Map<String, Boolean> reqTypeCode = new HashMap<>();
    if (typeCodesList != null) { // 跟严明和孙敬宇沟通，根据特征查询时，需要过滤调当前查询无关Target，因为下一步绑定操作找不到会报错
      typeCodesList.forEach(
              e -> {
                e.getCodes().forEach(code -> reqTypeCode.put(e.getType() + code, true));
              });
    }
    TargetRuleInfoDto targetRuleInfo = getTargetRuleInfoFromRGInfo(ruleGroupInfo);
    for (RuleGroupItemDto serverItem : ruleGroupInfo.getRuleItems()) { // 设置条件列表、结果列表
      RuleItemDto clientItem = new RuleItemDto();
      BeanUtils.copyProperties(serverItem, clientItem);
      if (serverItem.getRuleHs() == 2) {
        if (typeCodesList == null // 按id加载规则的场景，不会传入typeCodesList，先不做过滤
                || reqTypeCode.get(serverItem.getType() + serverItem.getCode()) != null) {
          targetRuleInfo.getTargets().add(clientItem);
        }
      } else { // 1-条件、3-条件部分Value引用字段、4-结果部分Value引用字段，均作为条件给框架，统一赋值传入
        targetRuleInfo.getSources().add(clientItem);
      }
    }
    return targetRuleInfo;
  }

  @NotNull // 特征组----------------------------------------
  private TargetRuleInfoDto getTargetRuleInfo4Cg(
          RelevantRuleGroupInfoDto ruleGroupInfo, List<CgIdCodesDto> cgIdCodesList) {
    Map<String, Boolean> reqCgIdCode = new HashMap<>();
    if (cgIdCodesList != null) { // 跟严明和孙敬宇沟通，根据特征查询时，需要过滤调当前查询无关Target，因为下一步绑定操作找不到会报错
      cgIdCodesList.forEach(
              e -> {
                e.getCodes().forEach(code -> reqCgIdCode.put(e.getCgId() + code, true));
              });
    }
    TargetRuleInfoDto targetRuleInfo = getTargetRuleInfoFromRGInfo(ruleGroupInfo);
    for (RuleGroupItemDto serverItem : ruleGroupInfo.getRuleItems()) { // 设置条件列表、结果列表
      RuleItemDto clientItem = new RuleItemDto();
      BeanUtils.copyProperties(serverItem, clientItem);
      if (serverItem.getRuleHs() == 2) {
        if (reqCgIdCode.get(serverItem.getCgId() + serverItem.getCode()) != null) {
          targetRuleInfo.getTargets().add(clientItem);
        }
      } else { // 1-条件、3-条件部分Value引用字段、4-结果部分Value引用字段，均作为条件给框架，统一赋值传入
        targetRuleInfo.getSources().add(clientItem);
      }
    }
    return targetRuleInfo;
  }

  /** 业务对象、特征、特征组通用 根据RelevantRuleGroupInfoDto构建TargetRuleInfoDto，Sources和Targets设置空列表，返回直接用 */
  @NotNull
  private TargetRuleInfoDto getTargetRuleInfoFromRGInfo(RelevantRuleGroupInfoDto ruleGroupInfo) {
    TargetRuleInfoDto targetRuleInfo = new TargetRuleInfoDto();
    targetRuleInfo.setId(ruleGroupInfo.getId());
    targetRuleInfo.setCode(ruleGroupInfo.getRuleGroupCode());
    targetRuleInfo.setName(ruleGroupInfo.getRuleGroupName());
    targetRuleInfo.setDataType(RelevantDataTypeEnum.getByCode(ruleGroupInfo.getDataType()));
    targetRuleInfo.setRuleType(RelevantRuleTypeEnum.getByCode(ruleGroupInfo.getRuleType()));
    targetRuleInfo.setSources(new ArrayList<>());
    targetRuleInfo.setTargets(new ArrayList<>());
    return targetRuleInfo;
  }

  //    private void setSourcesTargets(RelevantRuleGroupInfoDto ruleGroupInfo, // 设置条件列表、结果列表
  //            List<TypeCodesDto> typeCodesList, Map<String, Boolean> reqTypeCode,
  // TargetRuleInfoDto targetRuleInfo) {
  //        targetRuleInfo.setSources(new ArrayList<>());
  //        targetRuleInfo.setTargets(new ArrayList<>());
  //        for (RuleGroupItemDto serverItem : ruleGroupInfo.getRuleItems()) {
  //            RuleItemDto clientItem = new RuleItemDto();
  //            BeanUtils.copyProperties(serverItem, clientItem);
  //            if (serverItem.getRuleHs() == 2) {
  //                if (typeCodesList == null // 按id加载规则的场景，不会传入typeCodesList，先不做过滤
  //                        || reqTypeCode.get(serverItem.getType() + serverItem.getCode()) != null)
  // {
  //                    targetRuleInfo.getTargets().add(clientItem);
  //                }
  //            } else { // 1-条件、3-条件部分Value引用字段、4-结果部分Value引用字段，均作为条件给框架，统一赋值传入
  //                targetRuleInfo.getSources().add(clientItem);
  //            }
  //        }
  //    }

  //    private void setSourcesTargets4Cg( // 设置条件列表、结果列表
  //            RelevantRuleGroupInfoDto ruleGroupInfo, Map<String, Boolean> reqCgIdCode,
  // TargetRuleInfoDto targetRuleInfo) {
  //        targetRuleInfo.setSources(new ArrayList<>());
  //        targetRuleInfo.setTargets(new ArrayList<>());
  //        for (RuleGroupItemDto serverItem : ruleGroupInfo.getRuleItems()) {
  //            RuleItemDto clientItem = new RuleItemDto();
  //            BeanUtils.copyProperties(serverItem, clientItem);
  //            if (serverItem.getRuleHs() == 2) {
  //                if (reqCgIdCode.get(serverItem.getCgId() + serverItem.getCode()) != null) {
  //                    targetRuleInfo.getTargets().add(clientItem);
  //                }
  //            } else { // 1-条件、3-条件部分Value引用字段、4-结果部分Value引用字段，均作为条件给框架，统一赋值传入
  //                targetRuleInfo.getSources().add(clientItem);
  //            }
  //        }
  //    }
  private RelevantRuleMgmtService getRelevantRuleMgmtService() {
    if (this.relevantRuleMgmtService == null) {
      this.relevantRuleMgmtService = SpringContextHolder.getBean(RelevantRuleMgmtService.class);
    }

    return this.relevantRuleMgmtService;
  }
}
